/**************************************************************************************************
* Title: SumTimer.h
* Author: Gael Huber
* Description: High-precision timer capable of performing the basic operations such as start, stop,
*	pause, delta time, get current time.
**************************************************************************************************/
#ifndef __SUMTIMER_H__
#define __SUMTIMER_H__

#include <Windows.h>

const double maxDeltaTime = 1.0 / 60.0;

class Timer {
public:
	// Constructor
	inline Timer(void) 
		: frequency(0), currentTime(0), previousTime(0)
	{
		initialize();
	}

	// Destructor
	inline ~Timer(void)
	{ }

	// Start
	inline void start(void) {
		// Set the start time
		QueryPerformanceCounter((LARGE_INTEGER*)&currentTime);
		previousTime = currentTime;
	}

	// Pause
	inline void pause(void) {
		// Get the time and set both time keepers to the same value
		QueryPerformanceCounter((LARGE_INTEGER*)&currentTime);
		previousTime = currentTime;
	}

	// Resume
	inline void resume(void) {
		// Set the previous time to the current time value
		QueryPerformanceCounter((LARGE_INTEGER*)&previousTime);
	}

	// Get delta time as a float with consideration to the maximum permissible delta time
	inline float deltaTime_f(void) {
		// To ensure consistency in data, always call the same (i.e. more precise) delta time function 
		// and cast to a lower precision.		
		return (float) deltaTime_d();
	}

	// Get delta time as a double with consideration to the maximum permissible delta time
	inline double deltaTime_d(void) {
		// Get the current time
		QueryPerformanceCounter((LARGE_INTEGER*)&currentTime);

		// Find the difference
		INT64 difference = currentTime - previousTime;
		
		// Update the previuos time
		previousTime = currentTime;

		// Find dt
		double deltaTime = double(difference) / frequency;

		// If dt is larger than the maximum allowed, clamp it
		if(deltaTime > maxDeltaTime)
			deltaTime = maxDeltaTime;

		// Return deltaTime
		return deltaTime;
	}

	// Get delta time as a float without consideration to the maximum permissible delta time
	inline float deltaTime_f_no_max(void) {
		// To ensure consistency in data, always call the same (i.e. more precise) delta time function 
		// and cast to a lower precision.		
		return (float) deltaTime_d_no_max();
	}

	// Get delta time as a double without consideration to the maximum permissible delta time
	inline double deltaTime_d_no_max(void) {
		// Get the current time
		QueryPerformanceCounter((LARGE_INTEGER*)&currentTime);

		// Find the difference
		INT64 difference = currentTime - previousTime;
		
		// Update the previuos time
		previousTime = currentTime;

		// Find dt
		double deltaTime = double(difference) / frequency;

		// Return deltaTime
		return deltaTime;
	}


private:
	// Initialization function for the timer
	inline void initialize(void) {
		QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
	}

	INT64 frequency;	// Number of timer ticks per millisecond
	INT64 currentTime;	// Time at the most recent delta time call
	INT64 previousTime;	// Time at the previous delta time call


};

#endif